const path = require('path'),
    fs = require('fs-extra'),
    Uglifyjs = require('uglify-js'),
    rollup = require('rollup'),
    getPathInfo = require('./lib/getPathInfo'),
    getFiles = require('./lib/getFiles'),
    buildTsFile = require('./lib/buildTsFile'),


    // 获取传入的参数模式
    mode = (()=>{
        let argv = require('process').argv;
        return argv[argv.length - 1];
    })();

class Build {
    constructor(mode){
        const _ts = this,
            configPath = path.join(__dirname,'../tsconfig.json');

        if(fs.existsSync(configPath)){
            _ts.config = require(configPath);
        }else{
            throw new Error('tsconfig.json 配置文件不存在');
        };
        _ts.srcDir = path.join(__dirname,'..',_ts.config.compilerOptions.baseUrl);
        _ts.outDir = path.join(__dirname,'..',_ts.config.compilerOptions.outDir);
        _ts.timer = {};      // 文件监听计时器
        
        // 根据传入的模式执行相应的任务
        switch (mode) {
            case 'watch':
                _ts.watch();    
            break;
            case 'clear':
                _ts.clear();
            break;
            case 'compress':
                _ts.compress();
            break;
            case 'build':
                _ts.build();
            break;
            case 'merge':
                _ts.merge();
            break;
            default:
                throw new Error("传入的类型错误");
            break;
        }
    }
    merge(){
        const _ts = this;
        rollup.rollup({
            input:'./Assets/StreamingAssets/Scripts/main.js',
            cache:true,
            plugins:[
                //require('rollup-plugin-commonjs')()
            ]
        }).then(v => {
            let res = v.generate({
                format:'cjs',
                sourcemap:false
            });
            res.then(v => {
                console.log(v);
            })
        })
    }

    // 压缩目录内 JS
    compress(){
        const _ts = this;
        let files = getFiles(_ts.outDir),
            count = 0;
        files.forEach(item => {
            if(getPathInfo(item).extname === 'js'){
                let itemStr = fs.readFileSync(item,'utf-8'),
                    result = Uglifyjs.minify(itemStr);
                if(result.error){
                    throw new Error("文件压缩出错");
                };
                fs.writeFileSync(item,result.code);
                count++;
                console.log("文件压缩成功：",item);
            };
        });
        console.log(new Array(51).join("="));
        console.log(`共 ${count} 个文件压缩完成`);
    }

    // 清除目录 Js
    clear(){
        const _ts = this;
        fs.emptyDirSync(_ts.outDir);
        console.log(`目录清除成功：${_ts.outDir}`);
    }

    /**
     * 监听目录，如果文件有改动则进行编译
     */
    watch(){
        const _ts = this;

        fs.watch(_ts.srcDir,{recursive:true},(eventType, fileName)=>{
            let filePath = path.join(_ts.srcDir,fileName),
                outPath = filePath.replace(_ts.srcDir,_ts.outDir).replace(/\.(jsx|js|ts)$/,'.js'),
                filePathInfo = getPathInfo(filePath);
            if(filePathInfo.type === 'file' && _ts.isTs(filePath)){
                clearTimeout(_ts.timer[filePath]);
                _ts.timer[filePath] = setTimeout(()=>{
                    buildTsFile(filePath,outPath,'commonjs','inline');
                },200);
            };
        });
    }
    
    /**
     * 判断输入路径是否为 Ts 文件
     * @param {string} srcPath 输入路径
     * @returns Boolean
     */
    isTs(srcPath){
        return /^jsx|js|ts|es|es6$/.test(getPathInfo(srcPath).extname) && !/(\.d\.ts)$/.test(srcPath);
    }

    /**
     * 编译输入目录所有文件
     */
    build(isRelease){
        const _ts = this;
        _ts.clear();
        let nodeModulesPath = path.join(__dirname,'..','node_modules'),
            nodeModulesPathInfo = getPathInfo(nodeModulesPath);
        
        if(nodeModulesPathInfo.type === 'dir'){
            fs.symlinkSync(nodeModulesPath,path.join(_ts.outDir,'node_modules'));
        };

        let files = getFiles(_ts.srcDir);
        files.forEach(item => {
            if(_ts.isTs(item)){
                let outPath = item.replace(_ts.srcDir,_ts.outDir).replace(/\.(jsx|js|ts)$/,'.js');
                if(isRelease){
                    buildTsFile(item,outPath,'es6',false);
                }else{
                    buildTsFile(item,outPath,'commonjs','inline');
                }
            };
        });
    }
}

new Build(mode);